﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Xunit;
using Genuilder.Extensions.XamlVerifier;
using System.IO;
using Genuilder.Tests;
using Genuilder.Extensibility;

namespace Genuilder.Extensions.Tests
{
	public class XamlVerifierTest
	{
		const string TestProject = "../../Data/XamlVerifier";
		[Fact]
		public void CanUseExtension()
		{
			using(var testDirectory = new TestDirectory().Of(TestProject))
			{
				var p = Projects.InDirectory(testDirectory.DirectoryInfo.FullName).First();
				var feature = new ExtensibilityFeature();
				feature.AddExtension(new XamlVerifierExtension()
				{
					AutoCorrect = false
				});
				p.InstallFeature(feature);
				p.Save();
				p.Build();
			}
		}
		[Fact]
		public void CanReadXamlFile()
		{
			XamlVerifierReader reader = CreateReader("UserControl2.xaml");
			var one = reader.Read();
			Assert.Equal(new Location(9, 9), one.Location);
			Assert.IsType(typeof(StartVerify), one);
			AssertIsBinding(reader.Read(), "Namee", new Location(10, 26));
			AssertIsBinding(reader.Read(), "Addoess", new Location(10, 55));
			AssertIsBinding(reader.Read(), "Addresss.Detials", new Location(10, 90));
			var last = reader.Read();
			Assert.Equal(new Location(11, 9), last.Location);
			Assert.IsType(typeof(EndVerify), last);
		}

		[Fact]
		public void CanFindBindingPathError()
		{
			XamlVerifierEvaluator evaluator = new XamlVerifierEvaluator();
			evaluator.XamlFiles.Add(FilePath("UserControl2.xaml"));
			evaluator.CodeFiles.Add(FilePath("UserControl2ViewModel.cs"));

			var typeError = evaluator.NextError() as XamlVerifier.XamlVerifierTypeError;

			Assert.NotNull(typeError);
			Assert.Equal("Persno", typeError.TypeName);
			Assert.Equal("Person", typeError.Suggestion);
			Assert.Equal(new Location(9, 28), typeError.Location);

			var error = evaluator.NextError() as XamlVerifierPropertyError;

			Assert.NotNull(error);
			Assert.Equal("Persno", error.ClassName);
			Assert.Equal("Namee", error.PropertyName);
			Assert.Equal("Name", error.Suggestion);
			Assert.Equal(FilePath("UserControl2.xaml"), error.File);
			Assert.Equal(new Location(10, 35), error.Location);

			error = evaluator.NextError() as XamlVerifierPropertyError;

			Assert.Equal("Persno", error.ClassName);
			Assert.Equal("Addoess", error.PropertyName);
			Assert.Equal("Address", error.Suggestion);
			Assert.Equal(new Location(10, 69), error.Location);

			error = evaluator.NextError() as XamlVerifierPropertyError;

			Assert.Equal("Persno", error.ClassName);
			Assert.Equal("Addresss", error.PropertyName);
			Assert.Equal("Address", error.Suggestion);
			Assert.Equal(new Location(10, 104), error.Location);

			error = evaluator.NextError() as XamlVerifierPropertyError;

			Assert.Equal("Address", error.ClassName);
			Assert.Equal("Detials", error.PropertyName);
			Assert.Equal("Details", error.Suggestion);
			Assert.Equal(new Location(10, 113), error.Location);

			error = evaluator.NextError() as XamlVerifierPropertyError;

			Assert.Equal("Employee", error.ClassName);
			Assert.Equal("Nam", error.PropertyName);
			Assert.Equal("Name", error.Suggestion);
			Assert.Equal(new Location(13, 35), error.Location);

			typeError = evaluator.NextError() as XamlVerifier.XamlVerifierTypeError;

			Assert.Equal("Genuilder.Extensions.Tests.Dtaa.XomlVerifie.Persno", typeError.TypeName);
			Assert.Equal("Genuilder.Extensions.Tests.Data.XamlVerifier.Person", typeError.Suggestion);
			Assert.Equal(new Location(15, 28), typeError.Location);
		}

		[Fact]
		public void CanFindStartVerifyError()
		{
			XamlVerifierEvaluator evaluator = new XamlVerifierEvaluator();
			evaluator.XamlFiles.Add(FilePath("UserControl1.xaml"));
			evaluator.CodeFiles.Add(FilePath("UserControl2ViewModel.cs"));

			var error = evaluator.NextError() as XamlVerifierTypeError;

			Assert.NotNull(error);
			Assert.Equal("Personn", error.TypeName);
			Assert.Equal("Person", error.Suggestion);
			Assert.Equal(FilePath("UserControl1.xaml"), error.File);
			Assert.Equal(new Location(9, 33), error.Location);
		}

		[Fact]
		public void CanCorrectErrors()
		{
			XamlVerifierEvaluator evaluator = new XamlVerifierEvaluator();
			evaluator.XamlFiles.Add(FilePath("UserControl2.xaml"));
			evaluator.CodeFiles.Add(FilePath("UserControl2ViewModel.cs"));

			XamlCorrector corrector = new XamlCorrector();
			corrector.Evaluator = evaluator;
			corrector.AllErrors().ToList();

			var u = corrector.Corrections[FilePath("UserControl2.xaml")].Length;
			var t = File.ReadAllText(FilePath("UserControl2Right.xaml")).Length;
			Assert.Equal(
				File.ReadAllText(FilePath("UserControl2Right.xaml")),
				corrector.Corrections[FilePath("UserControl2.xaml")]
				);
		}

		private void AssertIsBinding(XamlVerifierNode node, string path, Location? location = null)
		{
			Assert.IsType(typeof(XamlBinding), node);
			XamlBinding binding = (XamlBinding)node;
			Assert.Equal(path, binding.Path);
			if(location != null)
			{
				Assert.Equal(location, binding.Location);
			}
		}

		private XamlVerifierReader CreateReader(string file)
		{
			return new XamlVerifierReader(File.ReadAllText(FilePath(file)));
		}
		private string FilePath(string name)
		{
			return "../../Data/XamlVerifier/" + name;
		}
	}
}
